﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NETMovie.Entities;

namespace NETMovie.Repositories.EF
{
    public class MovieRepository : AbstractRepository, IMovieRepository
    {
        public MovieRepository()
        {
            base.Initialize();
        }

        public Movie GetMovie(int movieID)
        {

            Movie dbMovie = cntx.Movies.First(m => m.MovieId == movieID);
            MovieCategory dbMovieCategory = dbMovie.Category;
            return dbMovie;
        }

        public CastMember[] GetMovieCastMembers(int movieID)
        {
            Movie dbMovie = cntx.Movies.First(m => m.MovieId == movieID);
            return dbMovie.CastMembers.ToArray();
        }

        public Movie GetMovie(string movieTitle)
        {

            Movie movie = cntx.Movies.SingleOrDefault(m => m.Title == movieTitle);

            return movie;
        }


        public IEnumerable<Movie> GetMovies(string title, string category, string keywords, bool showDelete) // keywords include actor, short summary, description
        {
            IQueryable<Movie> matches = cntx.Movies; 
             IEnumerable<Movie> movieList;
            
            if(!String.IsNullOrEmpty(title)  && title.Trim().Length > 0)
            {
                matches = matches.Where(a => a.Title.Contains(title));
            }
                  
            if(!String.IsNullOrEmpty(title)  && title.Trim().Length > 0)
            {
                matches = matches.Where(a => a.Category.CategoryCode == category);
            }
                if(!String.IsNullOrEmpty(keywords)  && keywords.Trim().Length > 0)
            {
                matches = matches.Where(a => a.Summary.Contains(keywords) || a.Description.Contains(keywords));
            }


                movieList = (from p in matches orderby p.Title select p).ToList();
                return movieList;
            
        }

        public int CreateMovie(Movie movie)
        {
            try
            {
                var dbCategory = GetCategory(movie.Category.CategoryCode);
                // For state sync
                movie.Category = dbCategory;
                cntx.AddToMovies(movie);
                cntx.SaveChanges();

                return cntx.Movies.SingleOrDefault(m => m.Title == movie.Title).MovieId;
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        public bool EditMovie(Movie movie)
        {
            Movie dbMovie = cntx.Movies.First(m => m.MovieId == movie.MovieId);

            dbMovie.Description = movie.Description;
            dbMovie.AvailableDate = movie.AvailableDate;
            dbMovie.Summary = movie.Summary;
            dbMovie.Title = movie.Title;
            dbMovie.ReleaseDate = movie.ReleaseDate;

            var dbCategory = GetCategory(movie.Category.CategoryCode);
            dbMovie.Category = dbCategory;
            cntx.SaveChanges();
            return true;
        }

        public MovieCategory GetCategory(string categoryCode)
        {
            var dbCategory = cntx.MovieCategories.FirstOrDefault(m => m.CategoryCode == categoryCode);
            return dbCategory;
        }

        public MovieCategory[] GetAllCategories()
        {
            return cntx.MovieCategories.ToArray();
        }

        public bool SaveMovie(Movie movie)
        {
            Movie dbMovie = cntx.Movies.SingleOrDefault(m => m.MovieId == movie.MovieId);
            dbMovie = movie;

            cntx.SaveChanges();

            return true;
        }

        public UserComment[] GetComments(int movieId)
        {
            Movie movie = cntx.Movies.FirstOrDefault(m => m.MovieId == movieId);
            if (movie != null)
                return movie.Comments.ToArray();
            return null; // movie doesn't exist? good to have check. repeat in business logic
        }

        public bool CreateComment(int movieId, UserComment comment)
        {
            var dbMovie = cntx.Movies.Where(m => m.MovieId == movieId).FirstOrDefault();
            if (dbMovie == null)
                return false;

            var dbUser = cntx.Users.Where(u => u.UserId == comment.User.UserId).DefaultIfEmpty(null).FirstOrDefault();
            if (dbUser == null)
                return false;

            comment.User = dbUser;
            dbMovie.Comments.Add(comment);
            return cntx.SaveChanges() > 0;
        }

        public bool AddMovieCastMember(IEnumerable<CastMember> castMemberList, int movieId)
        {


            Movie dbMovie = cntx.Movies.First(m => m.MovieId == movieId);
            if (dbMovie != null)
            {
                foreach (var castMember in castMemberList)
                {
                    dbMovie.CastMembers.Add(castMember);
            
                }
            }
            cntx.SaveChanges();
            return true;

        }

        public bool EditMovieCastMembers(IEnumerable<CastMember> castMemberList, int movieId)
        {


            Movie dbMovie = cntx.Movies.First(m => m.MovieId == movieId);

           CastMember [] dbCastMemberList = dbMovie.CastMembers.ToArray();
            if (dbMovie != null)
            {

                foreach (var castMember in castMemberList)
                {
                    //totally new castmember 
                    if (castMember.CastMemberId == 0) dbMovie.CastMembers.Add(castMember);
                    else
                    {
                        CastMember dbCastMember = cntx.CastMembers.First(m => m.CastMemberId == castMember.CastMemberId);
                      dbCastMember.Name = castMember.Name;
                      dbCastMember.Role = castMember.Role;

                    }
                }

             /*   if(dbCastMemberList.Length > 
                for (int i = 0; i < dbCastMemberList.Length; i++ )
                {
                    cntx.CastMembers.DeleteObject(dbCastMemberList[i]);
                }
*/
           
            }
            cntx.SaveChanges();
            return true;

        }

        public bool DeleteMovieCastMember(int castMemberId, int movieId)
        {
            Movie movie = cntx.Movies.First(m => m.MovieId == movieId);

            CastMember castMember = cntx.CastMembers.First(m => m.CastMemberId == castMemberId);
            movie.CastMembers.Remove(castMember);
            cntx.CastMembers.DeleteObject(castMember);
      
                //  cntx..DeleteObject(castMember);
            cntx.SaveChanges();
            return true;
        }


        public bool AddMovieArticle(Article article, int movieId)
        {
            Movie dbMovie = cntx.Movies.First(m => m.MovieId == movieId);
            if (dbMovie != null)
            {
              
                    dbMovie.Articles.Add(article);   
            }
            cntx.SaveChanges();
            return true;
        }

        public Article GetMovieArticle(int movieId)
        {
            Movie dbMovie = cntx.Movies.First(m => m.MovieId == movieId);
            Article [] articleArr = dbMovie.Articles.ToArray();
            if (articleArr.Length > 0)
            {
                return articleArr[0];
            }
            return null;
        }

     
    }
}
